/*
 * Copyright (C) 2012 The MjSip Open Source Project
 * 
 * This file is part of MjSip (http://www.mjsip.org)
 * 
 * Sipdroid is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
 * 
 * This source code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along with this source code; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package com.cvtt.voice.simple;

import android.content.Context;
import android.media.AudioManager;

import com.cvtt.voice.VoiceConfig;
import com.cvtt.voice.codec.Codecs;
import com.cvtt.voice.simple.net.CNativeSocket;
import com.zoolu.tools.LogLevel;

/** Audio launcher based on javax.sound */
public class SimpleVoice {
	/** Event logger. */

	/** Sample rate [bytes] */
	int sample_rate = 8000;
	/** Sample size [bytes] */
	int sample_size = 1;
	/** Frame size [bytes] */
	int frame_size = 160;
	/** Frame rate [frames per second] */
	int frame_rate = 50; // =sample_rate/(frame_size/sample_size);
	boolean signed = false;
	boolean big_endian = false;

	// String filename="audio.wav";

	/** Test tone */
	public static final String TONE = "TONE";

	/** Test tone frequency [Hz] */
	public static int tone_freq = 100;
	/** Test tone ampliture (from 0.0 to 1.0) */
	public static double tone_amp = 1.0;

	/** Runtime media process */
	Process media_process = null;

	int dir; // duplex= 0, recv-only= -1, send-only= +1;

	CNativeSocket socket = null;
	RTPStreamSender sender = null;
	RTPStreamReceiver receiver = null;

	private AudioManager am;

	// change DTMF
	boolean useDTMF = false; // zero means not use outband DTMF

	/** Costructs the audio launcher */
	public SimpleVoice(RTPStreamSender rtp_sender, RTPStreamReceiver rtp_receiver) {
		sender = rtp_sender;
		receiver = rtp_receiver;
		am = (AudioManager) VoiceConfig.getVoiceConfig().getContext().getSystemService(Context.AUDIO_SERVICE);
	}

	// Modified by huah in 2012-08-12
	/** Costructs the audio launcher */
	public SimpleVoice(int local_port, String remote_addr, int remote_port, Codecs.Map cm) {
		// log = logger;

		// TODO:Modified by huah in 2012-08-03 for debug Speex
		frame_size = cm.codec.frame_size();
		sample_rate = cm.codec.samp_rate();

		frame_rate = sample_rate / frame_size;
		useDTMF = false;
		am = (AudioManager) VoiceConfig.getVoiceConfig().getContext().getSystemService(Context.AUDIO_SERVICE);
		try {
			socket = new CNativeSocket(local_port);

			receiver = new RTPStreamReceiver(socket, cm);

			sender = new RTPStreamSender(true, cm, frame_rate, frame_size, socket, remote_addr, remote_port);
			sender.setSyncAdj(2);
			// sender.setDTMFpayloadType(dtmf_pt);
			// dir = direction;
			//
			// // receiver
			// if (dir <= 0) {
			// printLog("new audio receiver on " + local_port, LogLevel.MEDIUM);
			// receiver = new RTPStreamReceiver(socket, payload_type);
			// }
			//
			// // sender
			// if (dir >= 0) {
			// printLog("new audio sender to " + remote_addr + ":"
			// + remote_port, LogLevel.MEDIUM);
			// // audio_input=new AudioInput();
			// sender = new RTPStreamSender(true, payload_type, frame_rate,
			// frame_size, socket, remote_addr, remote_port);
			// sender.setSyncAdj(2);
			// sender.setDTMFpayloadType(dtmf_pt);
			// }

		}
		catch (Exception e) {
			printException(e, LogLevel.HIGH);
		}
	}

	/** Costructs the audio launcher */
	public SimpleVoice(int local_port, String remote_addr, int remote_port, int direction, String audiofile_in, String audiofile_out, int sample_rate, int sample_size, int frame_size,
			Codecs.Map payload_type, int dtmf_pt) {

		// TODO:Modified by huah in 2012-08-03 for debug Speex
		this.frame_size = frame_size;
		this.sample_rate = sample_rate;

		frame_rate = sample_rate / frame_size;
		useDTMF = (dtmf_pt != 0);
		am = (AudioManager) VoiceConfig.getVoiceConfig().getContext().getSystemService(Context.AUDIO_SERVICE);
		try {
			socket = new CNativeSocket(local_port);
			dir = direction;

			// receiver
			if (dir <= 0) {
				printLog("new audio receiver on " + local_port, LogLevel.MEDIUM);
				receiver = new RTPStreamReceiver(socket, payload_type);
			}

			// sender
			if (dir >= 0) {
				printLog("new audio sender to " + remote_addr + ":" + remote_port, LogLevel.MEDIUM);
				// audio_input=new AudioInput();
				sender = new RTPStreamSender(true, payload_type, frame_rate, frame_size, socket, remote_addr, remote_port);
				sender.setSyncAdj(2);
				sender.setDTMFpayloadType(dtmf_pt);
			}

		}
		catch (Exception e) {
			printException(e, LogLevel.HIGH);
		}
	}

	/** Starts media application */
	public boolean startMedia() {
		printLog("starting java audio..", LogLevel.HIGH);

		// TODO:Modified by huah in 2012-08-03 for debug Speex
		// Speex spx = Speex.getInstance();
		// spx.init(frame_size, sample_rate);

		if (receiver != null) {
			printLog("start receiving", LogLevel.LOW);
			receiver.start();
		}

		if (sender != null) {
			printLog("start sending", LogLevel.LOW);
			sender.start();
		}

		return true;
	}

	/** Stops media application */
	public boolean stopMedia() {
		printLog("halting java audio..", LogLevel.HIGH);
		if (sender != null) {
			sender.halt();
			sender = null;
			printLog("sender halted", LogLevel.LOW);
		}
		if (receiver != null) {
			receiver.halt();
			receiver = null;
			printLog("receiver halted", LogLevel.LOW);
		}
		// Modified by huah in 2012-08-11 for debug
		// if (socket != null)
		// socket.close();

		return true;
	}

	public void setMode(boolean isCall) {
		receiver.reset();
	}

	public void setSpeaker(boolean enable) {
		// Modified by huah in 2012-08-16
		// am.setMode(AudioManager.ROUTE_SPEAKER);
		RTPStreamReceiver.speakerOn = enable;
		am.setSpeakerphoneOn(enable);
	}

	public boolean muteMedia(boolean enable) {
		if (sender != null)
			return sender.mute(enable);
		return false;
	}

	public int speakerMedia(int mode) {
		if (receiver != null)
			return receiver.speaker(mode);
		return 0;
	}

	public void bluetoothMedia() {
		if (receiver != null)
			receiver.bluetooth();
	}

	// change DTMF
	/** Send outband DTMF packets **/
	public boolean sendDTMF(char c) {
		if (!useDTMF)
			return false;
		sender.sendDTMF(c);
		return true;
	}

	// ****************************** Logs *****************************

	/** Adds a new string to the default Log */
	private void printLog(String str) {
		printLog(str, LogLevel.HIGH);
	}

	/** Adds a new string to the default Log */
	private void printLog(String str, int level) {
		if (VoiceConfig.LOG_ENABLE == false)
			return;
		if (level <= LogLevel.HIGH)
			System.out.println("AudioLauncher: " + str);
	}

	/** Adds the Exception message to the default Log */
	void printException(Exception e, int level) {
		if (VoiceConfig.LOG_ENABLE == false)
			return;
		if (level <= LogLevel.HIGH)
			e.printStackTrace();
	}

}